package com.hanxiaozhang.threadbase1ndedition.no9container.no4concurrentcontainer;

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;

/**
 * 功能描述: <br>
 * 〈TransferQueue〉
 * <p>
 * 特点：
 * 它是LinkedBlockingQueue和SynchronousQueue的合体；
 * 生产者会一直阻塞，直到所添加到队列的元素被某一个消费者所消费；
 * 底层：
 * LinkedTransferQueue使用CAS操作实现一个非阻塞的方法。
 * 场景：
 * 确定有人去处理，才会有反馈，收钱。
 * 当我们不想生产者过度生产消息时，TransferQueue可能非常有用，
 * 可避免发生OutOfMemory错误。在这样的设计中，消费者的消费能力将决定生产者产生消息的速度。
 *
 * @Author:hanxinghua
 * @Date: 2021/11/21
 */
public class No12TransferQueue {



    /*
    1. TransferQueue<E> extends BlockingQueue<E>


    2. TransferQueue接口中的新方法：
    ## boolean tryTransfer(E e)
    如果可能，立即将元素转移给等待的消费者。即，如果存在消费者已经等待接收它（在take()或poll(long，TimeUnit)）中，
    则立即传送指定的元素，否则返回false。

    ## void transfer(E e) throws InterruptedException
    将元素转移给消费者，如果需要的话等待。即，如果存在一个消费者已经等待接收它（在take()或poll(long，TimeUnit)）中，
    则立即传送指定的元素，否则等待直到元素由消费者接收。

    ## boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException;
    在上面方法的基础上设置超时时间

    ## boolean hasWaitingConsumer();
    如果至少有一位消费者在等待，则返回true

    ## int getWaitingConsumerCount();
    返回等待消费者人数的估计值

     */


    public static void main(String[] args) throws InterruptedException {

        LinkedTransferQueue<String> queue = new LinkedTransferQueue<>();

        // 消费者
        new Thread(() -> {
            System.out.println("---- consumer start");
            try {
                while (true) {
                    // 睡眠1s
                    TimeUnit.MILLISECONDS.sleep(1000);
                    System.out.println("consumer get " + queue.take());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        // 生产者
        System.out.println("---- producer start");

        // 生产者将元素转移给消费者，如果没有消费者等待
        long startTime = System.currentTimeMillis();
        queue.transfer("a");
        long endTime = System.currentTimeMillis();
        System.out.println("producer a wait time is " + (endTime - startTime));

        // 如果可能，立即将元素转移给等待的消费者，如果没有消费者等待，返回false，次数传输失败
        startTime = System.currentTimeMillis();
        System.out.println("tryTransfer return is " + queue.tryTransfer("b"));
        endTime = System.currentTimeMillis();
        System.out.println("producer b wait time is " + (endTime - startTime));

        // 测试普通方法
        startTime = System.currentTimeMillis();
        queue.put("c");
        endTime = System.currentTimeMillis();
        System.out.println("producer c wait time is " + (endTime - startTime));

    }
}
